
function get_variable_value() {
    local varname=$1
    if [[ $ZSH_VERSION ]]; then
        echo "${(P)$(echo $varname)}"
    elif [[ $BASH_VERSION ]]; then
        echo "${!varname}"
    else
        eval "echo \"\$$varname\""
    fi
}

function path_push_back() {
    # <varname> <pathes> <flags...>
    if [[ $# < 2 ]]; then
        >&2 echo "path_push_back: invalid args"
        exit 1
    fi

    local varname=$1; shift
    local arrIN=()

    # https://zsh.sourceforge.io/Doc/Release/Options.html
    if [[ $ZSH_VERSION ]]; then
        setopt sh_word_split
        local IFS=$':'; arrIN=($1); unset IFS; shift
        unsetopt sh_word_split
    else
        local IFS=$':'; arrIN=($1); unset IFS; shift
    fi

    # check if empty
    if [[ ${#arrIN[@]} == 0 ]]; then
        # echo "path_push_back: $varname: no pathes to add"
        return
    fi

    # flags
    local FORCE=0
    local WARN=0
    if [[ $# > 0 ]]; then
        # echo $@
        local i
        for i in "$@"; do
            if [[ -z $i ]]; then
                continue
            fi
            if [[ $i[1] != '-' ]]; then
                continue
            fi

            i=$(echo $i | tr '[:upper:]' '[:lower:]')
            # echo "\$i=$i"
            if [[ $i == '-f' || $i == '--force' ]]; then
                FORCE=1
                continue
            fi
            if [[ $i == '-q' || $i == '--quiet' ]]; then
                WARN=0
                continue
            fi
        done
        unset i
    fi

    # apply
    local new=$(get_variable_value $varname)
    # echo "$varname: \"$new\" + @($arrIN)"
    # echo "\$FORCE=$FORCE"
    # echo "\$WARN=$WARN"

    # zsh will echo the previous value if the variable is set
    local i
    for i in "${arrIN[@]}"; do
        if [[ -z "$i" ]]; then
            continue
        fi

        if [[ ! -d "$i" ]]; then
            if [[ $FORCE > 0 ]]; then
                if [[ $WARN > 0 ]]; then
                    echo "path_push_back: $varname: force add non-found dir: $i"
                fi
            else
                if [[ $WARN > 1 ]]; then
                    >&2 echo "path_push_back: $varname: dir not found: $i"
                fi
                continue
            fi
        else
            true # nop
            # echo "$varname found: $i"
        fi

        if [[ -z $new ]]; then
            new="$i"
        else
            new+=":$i"
        fi
    done
    # echo "$varname updated: $new"

    # declare "$varname"="$new"
    export "$varname"="$new"

    # local variables doesn't need to be unset
    # unset varname WARN new arrIN i
}

function apply_pathes() {
    local i

    local PATH_next=""
    for i in {0..4}; do
        path_push_back PATH_next "$(get_variable_value PATH_$i)" -f
        path_push_back PATH_next "$(get_variable_value PATH_opt$i)"
        unset PATH_$i
        unset PATH_opt$i
    done
    export PATH_OLD="$PATH"
    export PATH="${PATH_next}"

    local MANPATH_next=""
    for i in {0..1}; do
        path_push_back MANPATH_next "$(get_variable_value MANPATH_$i)" -f
        unset MANPATH_$i
    done
    export MANPATH_OLD="$MANPATH"
    export MANPATH="${MANPATH_next}"
}

apply_pathes
unset apply_pathes

# [xp] maybe use it later, so don't unset it now
# unset path_push_back

true
